package dao;

import common.*;
import database.DatabaseException;
import java.util.*;
import presentation.*;
import runtime.RuntimeInstanceFactory;
import templates.*;
import utils.GenericPair;

public class Entity implements EntityPresentation {

    private static SortingStyle style;
    private short uid;
    private Iterable<Property> properties;
    private Collection<PresentationElement> presentations;

    public Entity(short uid) {
        this.uid = uid;
        properties = new LinkedList<Property>();
        presentations = new LinkedList<PresentationElement>();
    }

    public static Entity newInstance(short uid) {
        Entity e = new Entity(uid);
        e.parse(new EntityInitializer());
        return e;
    }

    public Property getProperty(short uid) {
        Property result = null;
        for (Property p : properties) {
            if (uid == p.getUid()) {
                result = p;
                break;
            }
        }
        return result;
    }

    public Iterable<Property> getPropertyCollection() {
        return properties;
    }

    public PresentationElement getPresentationElement(String alias) {
        PresentationElement result = null;
        for (PresentationElement pe : presentations) {
            if (pe.getTemplate().getAlias().equals(alias)) {
                result = pe;
                break;
            }
        }
        return result;
    }

    @Override
    public PresentationElement getPresentationElement(short uid) {
        PresentationElement result = null;
        for (PresentationElement pe : presentations) {
            if (pe.getUid() == uid) {
                result = pe;
                break;
            }
        }
        return result;
    }

    public static void sort(List<EntityPresentation> container, short uid) {
        style = Application.getInstance().getSortingStyle(uid);
        Collections.sort(container, new EntityComparator());
    }

    public void parse(Initializer i) {
        properties = (Iterable<Property>) i.init(uid);
        Application app = Application.getInstance();
        Template template = app.getTemplate(uid);
        Iterable<PresentationTemplate> container = template.getPresentationTemplateCollection();
        for (PresentationTemplate pt : container) {
            RuntimeInstanceFactory factory = new PresentationElementFactory();
            PresentationElement pe = (PresentationElement) factory.getObject(pt.getTypeName());
            if (pt.getTypeName().equals("LinkElement")) {
                pe.setParam(LinkElement.PRIMARY_KEY, getPrimaryKeyValue());
            }
            //pe.setName(pt.getName());
            //pe.setAlias(pt.getAlias());
            pe.setUid(pt.getUid());
            String value = getProperty(pt.getPropertyUid()).getValue().toString();
            PropertyTemplate pTemplate = template.getPropertyTemplate(pt.getPropertyUid());
            if (!pTemplate.isNullEnabled() || !value.equals(pTemplate.getNullValue())) {

                pe.setValue(value);

                if (pTemplate.isForeignKey()) {

                    short newUid = pTemplate.getExternalUid();
                    Entity e2 = null;
                    if (EntityCash.canUse()) {
                        e2 = EntityCash.findEntity((short) (newUid & 0xFF00), pe.getValue());
                    } else {
                        EntityDAO dao = new EntityDAO((short) (newUid & 0xFF00));
                        try {
                            e2 = (Entity) dao.findByPrimaryKey(pe.getValue());
                        } catch (DatabaseException ex) {
                            throw new RuntimeException(ex);
                        }
                    }

                    Iterator<GenericPair<String, Boolean>> it2 = pt.getExternals().iterator();
                    int j = 0;
                    while (it2.hasNext()) {
                        GenericPair<String, Boolean> ext = it2.next();
                        if (e2 != null) {
                            PresentationElement p2 = e2.getPresentationElement(ext.getFirst());
                            List<Object> externalMap = new LinkedList<Object>();
                            externalMap.add(p2);
                            externalMap.add(ext.getSecond());
                            pe.setParam(LinkElement.ADD_EXTERNAL, externalMap);
                        }
                    }
                }
            } else {
                pe.setValue(pt.getNullValue());
            }
            presentations.add(pe);
        }
    }

    @Override
    public Iterable<PresentationElement> getPresentationCollection() {
        return (Iterable<PresentationElement>) presentations;
    }

    @Override
    public int compareTo(EntityPresentation o) {
        int r = 0;
        short propertyUid = getPresentationElement(style.getParam()).getTemplate().getPropertyUid();
        Property p1 = getProperty(propertyUid);
        Property p2 = ((Entity) o).getProperty(propertyUid);
        r = (style.isAscending()) ? p1.getValue().compareTo(p2.getValue()) : p2.getValue().compareTo(p1.getValue());
        return r;
    }

    @Override
    public String getPrimaryKeyValue() {
        String result = "";
        for (PresentationElement pe : presentations) {
            if (pe.getPropertyTemplate().isPrimaryKey()) {
                result = pe.getValue();
                break;
            }
        }
        return result;
    }

    public boolean isPrimaryKeyPresentation(PresentationElement pe) {
        return pe.getPropertyTemplate().isPrimaryKey();
    }

    public short getUid() {
        return uid;
    }
}
